package net.test;

/**
 * 64进制和10进制的转换类
 * 
 */
public class CompressEncodeing {
	final static String PHOTOS_PREFIX = "H";
	final static String DEFUALT_IMAGE_SUBFIX = ".jpg";
	final static String PLACEHOLDER = "-";
	final static String UNDERLINE = "_";
	final static String SEPARATOR = "/";
	final static String DOT = ".";
	final static String[] IMAGES_TYPE = { "bmp", "gif", "jpg", "png" };
	final static char[] digits = { '0', '1', '2', '3', '4', '5', '6', '7', '8',
			'9', 'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l',
			'm', 'n', 'o', 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 'x', 'y',
			'z', 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L',
			'M', 'N', 'O', 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y',
			'Z', '+', '/', };

	/**
	 * @param args
	 */
	public static void main(String[] args) {
		String url = getEncodePhotoUrl(1234567890, "png");
		System.out.println(url);

		url = getDecodePhotoName(url + "_640x480.png");

		System.out.println(url);

	}

	/**
	 * 根据 userID 返回图片的 URL 编码 编码规则，共四段组成
	 * 编码前：H(1位长相册类型)-1234567890(10位长用户ID)-1325137433192（13位毫秒）-2（1位随机码）-3
	 * (图片类型码) 编码后：H(1位长相册相册)19Bwbi(6位长用户ID)ji8m99E（7位毫秒）-n(1位随机码)
	 * 例：H19Bwbiji8m99E-n
	 * 
	 * @param userID
	 * @param shift
	 * @return encoded url
	 */
	public static String getEncodePhotoUrl(long userID, String suffix) {
		int suffixCode = -1;
		for (int i = 0; i < IMAGES_TYPE.length; i++) {
			if (IMAGES_TYPE[i].indexOf(suffix) != -1) {
				suffixCode = i;
				break;
			}
		}
		return PHOTOS_PREFIX
				+ prefixFormat(CompressNumber(userID, 6), 6)
				+ prefixFormat(CompressNumber(System.currentTimeMillis(), 6), 7)
				+ (CompressNumber((int) (Math.random() * 10), 6))
				+ (suffixCode == -1 ? 0 : suffixCode);
	}

	/**
	 * 根据编码后的图片的 URL 返回真实的图片文件名 编码规则
	 * 解码前：H(1位长相册相册)19Bwbi(6位长用户ID)ji8m99E（7位毫秒）-n(2位随机码)_640x480(size).png(后缀)
	 * 解码后：H(1位长相册类型)/1234567890(10位长用户ID)/1325137433192（13位毫秒）23（2位随机码）
	 * 例：H19Bwbiji8m99E-n_640x480.png ->
	 * /H/1234567890/132513743319223_640x480.png
	 * 
	 * @param url
	 * @return decoded photo file name
	 */
	public static String getDecodePhotoName(String url) {
		// 必须是大于 16位
		if (url == null || url.length() < 16)
			return null;
		String encodedUrl = url.substring(0, url.indexOf(UNDERLINE));
		// 有效编码必须是 16 位
		if (encodedUrl == null || encodedUrl.length() != 16)
			return null;

		String size = url.substring(url.indexOf(UNDERLINE), url.indexOf(DOT));
		String suffix = url.substring(url.indexOf(DOT), url.length());

		return encodedUrl.substring(0, 1) + SEPARATOR
				+ UnCompressNumber(encodedUrl.substring(1, 7)) + SEPARATOR
				+ UnCompressNumber(encodedUrl.substring(7, 14))
				+ UnCompressNumber(encodedUrl.substring(14, 15)) + size
				+ suffix;

	}

	/**
	 * 把10进制的数字转换成64进制
	 * 
	 * @param number
	 * @param shift
	 * @return
	 */
	private static String CompressNumber(long number, int shift) {
		char[] buf = new char[64];
		int charPos = 64;
		int radix = 1 << shift;
		long mask = radix - 1;
		do {
			buf[--charPos] = digits[(int) (number & mask)];
			number >>>= shift;
		} while (number != 0);
		return new String(buf, charPos, (64 - charPos));
	}

	/**
	 * 把64进制的字符串转换成10进制
	 * 
	 * @param decompStr
	 * @return
	 */
	private static long UnCompressNumber(String decompStr) {
		long result = 0;
		for (int i = decompStr.length() - 1; i >= 0; i--) {
			if (i == decompStr.length() - 1) {
				result += getCharIndexNum(decompStr.charAt(i));
				continue;
			}
			for (int j = 0; j < digits.length; j++) {
				if (decompStr.charAt(i) == digits[j]) {
					result += ((long) j) << 6 * (decompStr.length() - 1 - i);
				}
			}
		}
		return result;
	}

	/**
	 * 
	 * @param ch
	 * @return
	 */
	private static long getCharIndexNum(char ch) {
		int num = ((int) ch);
		if (num >= 48 && num <= 57) {
			return num - 48;
		} else if (num >= 97 && num <= 122) {
			return num - 87;
		} else if (num >= 65 && num <= 90) {
			return num - 29;
		} else if (num == 43) {
			return 62;
		} else if (num == 47) {
			return 63;
		}
		return 0;
	}

	/**
	 * 格式化文本，按固定长度，位数不够在前面补“-”
	 * 
	 * @param soucre
	 *            原来的文本
	 * @param length
	 *            固定长度值
	 * @return String 格式化后文本
	 */
	public static String prefixFormat(String soucre, int length) {
		return String.format("%" + length + "s", soucre).replaceAll(" ",PLACEHOLDER);
	}
}

